package com.itkjb.leisurely.center.sys.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.itkjb.leisurely.authentication.core.common.properties.SecurityProperties;
import com.itkjb.leisurely.authentication.core.common.support.AuthenticationCache;
import com.itkjb.leisurely.authentication.core.common.utils.Oauth2TokenUtil;
import com.itkjb.leisurely.core.base.BaseResult;
import com.itkjb.leisurely.core.log.annotion.LeisurelyRequestLog;
import com.itkjb.leisurely.core.log.model.LogTypeEnum;
import com.itkjb.leisurely.core.util.Md5Utils;
import com.itkjb.leisurely.core.util.RedisUtil;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.oauth2.provider.approval.Approval;
import org.springframework.security.oauth2.provider.approval.ApprovalStore;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.Principal;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Copyright (C), 2018-2099
 * FileName: LoginProcessor
 * Author:   lix
 * Date:     2019-05-15 13:59
 * Description: 登陆处理器
 * Version: V1.0.0
 */
@Slf4j
@Controller
public class DefaultLoginPage {
    private RequestCache requestCache = new HttpSessionRequestCache();

    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    @Autowired
    private SecurityProperties securityProperties;

    @Autowired
    private ObjectMapper objectMapper;


    @Autowired
    private JdbcClientDetailsService clientDetailsService;

    @Autowired
    private ApprovalStore approvalStore;

    private static String AUTH_TYPE = "bearer ";

    @Autowired
    AuthenticationCache authenticationCache;

    @Autowired
    RedisUtil redisUtil;
    /**
     * 当需要身份认证时，跳转到这里
     *
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @GetMapping("/login")
    public String  requireAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws IOException {

        SavedRequest savedRequest = requestCache.getRequest(request, response);
        if(!StringUtils.isEmpty(request.getParameter("errorMsg"))){
            request.setAttribute("errorMsg", request.getParameter("errorMsg"));
        }
        if("/login".equals(request.getRequestURI())){
            return "login";
        }
        // 有上一次访问的url缓存
        if (savedRequest != null) {
            String targetUrl = savedRequest.getRedirectUrl();
            log.info("引发跳转的请求是:" + targetUrl);
            if (StringUtils.endsWithIgnoreCase(targetUrl, ".html")) {
                if(StringUtils.isEmpty(securityProperties.getWeb().getLoginPage())){
                    return "login";
                }else{
                    // 跳转至配置的rul
                    redirectStrategy.sendRedirect(request, response, securityProperties.getWeb().getLoginPage());
                    return null;
                }
            }else{
                returnJsonData(request,response);
                return null;
            }
        }

        return "login";
    }

    /**
     * 处理返回json
     * @param request
     * @param response
     * @throws IOException
     */
    private void returnJsonData(HttpServletRequest request, HttpServletResponse response) throws IOException{
        BaseResult<Object> res = new BaseResult<>();
        res.setCode(HttpStatus.UNAUTHORIZED.value()+"");
        res.setMsg("访问的服务需要身份认证，请引导用户到登录页");
        response.setContentType("application/json;charset=UTF-8");
        // 这里http状态改为 200，整个程序的ajax请求根据 code 值判断
        response.setStatus(HttpStatus.OK.value());
        response.getWriter().write(objectMapper.writeValueAsString(res));
    }




    @RequestMapping(value = "/_man_clients" ,method = {RequestMethod.POST, RequestMethod.GET})
    public ModelAndView clients(Map<String,Object> model, Principal principal){

        List<Approval> approvals=clientDetailsService.listClientDetails().stream()
                .map(clientDetails -> approvalStore.getApprovals(principal.getName(),clientDetails.getClientId()))
                .flatMap(Collection::stream)
                .collect(Collectors.toList());

        model.put("approvals",approvals);
        model.put("clientDetails",clientDetailsService.listClientDetails());
        return new ModelAndView("clients",model);

    }
    @GetMapping("/")
    public ModelAndView root(Map<String,Object> model, Principal principal){

        model.put("username", principal.getName());
        return new ModelAndView("index",model);

    }

    @RequestMapping(value = "/userInfo" , method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public BaseResult<Principal> userInfo(Map<String,Object> model, Principal principal){

        BaseResult<Principal>res  = new BaseResult<>(true);
        res.setData(principal);
        return res;

    }

    @RequestMapping(value = "/user/logout",method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    @ApiOperation(value="用户退出",notes="")
    @LeisurelyRequestLog(value = "用户登出",type = LogTypeEnum.LOGOUT)
    public BaseResult<Object> user(HttpServletRequest request, Principal principal){
        BaseResult<Object>res  = new BaseResult<>(true);
        String token = Oauth2TokenUtil.getTokenStringFromHeader(request);
        if(token != null){
            // 清除登陆的token
            String tokenKey = Md5Utils.getMD5(token);
            authenticationCache.clearAllAuthenticationCache(tokenKey);
        }
        return res;

    }

}
